package com.example.learningspringboot.email.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
@Slf4j
public class EmailUtil {

    /**
     * 在Bean的依赖注入上使用的构造函数方式,依赖注入的Bean对象使用final来修饰;
     *下面是这样做的原因:
     * 1.不可变性 (Immutability)
     * 优势:一旦在构造函数中赋值，就不能再被修改,防止在类的其他方法中意外重新赋值,确保依赖关系在整个对象生命周期中保持一致
     * 2.线程安全，具体需要DeepSeek
     * 3.明确的设计意图
     * 4.编译时检查,如果没有初始化final字段，编译器会报错,如果忘记这行赋值，编译错误：variable productRepository might not have been initialized
     * 5.与Spring框架的协作
     * 6.防止NPE（空指针异常），我们可以在构造函数赋值的时候进行null检查
     * 7.函数式编程风格
     * 8.与记录类（Record）的兼容性
     * 总结:
     * 使用final修饰注入的bean是Spring开发中的最佳实践，因为它：
     * ✅ 增强安全性：防止意外修改依赖
     * ✅ 提高可读性：明确表达设计意图
     * ✅ 支持线程安全：天然的不可变对象
     * ✅ 便于测试：依赖关系明确且稳定
     * ✅ 编译时保障：编译器帮助检查初始化
     * ✅ 符合函数式编程原则：鼓励不可变性
     */
    private final JavaMailSender javaMailSender;

    /**
     * 这里我们使用的构造函数进行依赖注入
     * 在单一构造函数下可省略
     */
    @Autowired
    public EmailUtil(JavaMailSender javaMailSender) {
        this.javaMailSender = javaMailSender;
    }


    public boolean sender(SimpleMailMessage smm) {
        return sendEmailLambda(smm);
    }

    private boolean sendEmailLambda(SimpleMailMessage smm) {
        try {
            // 使用Lambda创建Runnable
            Runnable emailTask = () -> {
                try {
                    System.out.println("Lambda - 发送邮件给: " + Arrays.toString(smm.getTo()));
                    // 实际邮件发送逻辑
                    simulateEmailSending(smm);
                    System.out.println("Lambda - 发送成功: " + Arrays.toString(smm.getTo()));
                } catch (Exception e) {
                    System.err.println("Lambda - 发送失败: " + Arrays.toString(smm.getTo()));
                }
            };
            new Thread(emailTask).start();
            return Boolean.TRUE;
        }catch (Exception e){
            return Boolean.FALSE;
        }
    }

    private void simulateEmailSending(SimpleMailMessage smm) {
        log.info("发送开始!!");
        // 实际邮件发送代码...
        javaMailSender.send(smm);
        log.info("发送完成!!");
    }

}
